<script lang="ts" setup>
import { reactive, ref, computed, onMounted } from 'vue'
import { useMap } from '@/hooks/useMap'
import { queryBikeTrack, queryBikeTrackDate } from '@/api/bike'
import { queryBikeTrackResponseData, bikeGPSListType } from '@/api/bike/types/bike'
import { getToken } from '@/utils/cache/cookies'
import { useRoute } from 'vue-router'
import dayjs from 'dayjs'
import duration from 'dayjs/plugin/duration'
import { formatMeter } from '@/utils/index'
import SearchPlace from '@/components/map/SearchPlace.vue'
import { ElMessage } from 'element-plus'
import StartIcon from '@/assets/map/bikeLocus/starticon.png'
import CyclingIcon from '@/assets/map/bikeLocus/cyclingicon.png'
import EndIcon from '@/assets/map/bikeLocus/endicon.png'
import CrossMarkerIcon from '@/assets/map/bikeLocus/crossmarker.png'
import StartMarkerIcon from '@/assets/map/bikeLocus/startmarker.png'
import EndMarkerIcon from '@/assets/map/bikeLocus/endmarker.png'
import MarkerIcon from '@/assets/map/bikeLocus/marker.png'
import { useActivated } from '@/hooks/useActivated'
import { onActivated } from 'vue'
defineOptions({
  name: 'LongBikeLocus'
})
/** 扩展时长插件 */
dayjs.extend(duration)
const route = useRoute()
const loading = ref<boolean>(false)
const dialogVisible = ref<boolean>(false)
const isInit = ref<boolean>(false)
const mapContainer = ref<HTMLDivElement>()
const center = reactive({
  longtitude: 0,
  latitude: 0
})
const { map, auto, initAmap, placeSearch, geocoder } = useMap(mapContainer, [
  Number(center.longtitude),
  Number(center.latitude)
])

const init = async () => {
  isInit.value = await initAmap()
  handleInit()
}
const handleInit = () => {
  if (isInit.value && map.value) {
    getBikeTrackDateData()
    dialogVisible.value = true
  }
}
const watchParams = reactive({
  bikeId: route.query.bikeId
})
onMounted(() => {
  init()
})
onActivated(() => {
  watchParams.bikeId = route.query.bikeId
})
useActivated(
  watchParams,
  { watchParams },
  [{ key: 'bikeId', path: 'watchParams.bikeId' }],
  handleInit,
  []
)
/**
 * 获取长租车辆轨迹日期
 * @param time - 当前日期
 * @param disabledDate - 禁用日期
 */
const time = ref<string>('')
const dateData = ref<string[]>([])
const disabledDate = (date: Date) => {
  const dateString = dayjs(date).format('YYYY-MM-DD')
  return !dateData.value.includes(dateString)
}

const getBikeTrackDateData = async () => {
  try {
    const res = await queryBikeTrackDate({
      token: getToken() ?? '',
      bikeId: watchParams.bikeId as string
    })
    if (res.statusCode === '0') {
      time.value = res.data[0]
      dateData.value = res.data
      getBikeTrackData()
    }
  } catch (error) {
    console.error(error)
  }
}

/**
 * 根据日期获取长租车辆轨迹
 * @param filteredData - 过滤bikeGPSList无数据的data
 * @param originData - 过滤后无数据处理的data
 */
const originData = ref<queryBikeTrackResponseData[]>([])
const getBikeTrackData = async () => {
  if (isPlay.value == 'primary') {
    isPlay.value = ''
    marker.value?.stopMove()
    marker.value?.setPosition(start.LngLat!)
    marker.value?.setLabel({
      content: ''
    })
    polyLines.value.forEach((item) => item.show())
  }
  try {
    loading.value = true
    const res = await queryBikeTrack({
      token: getToken() ?? '',
      bikeId: watchParams.bikeId as string,
      startTime: time.value
    })
    if (res.statusCode === '0') {
      if (Array.isArray(res.data) && res.data.length > 0) {
        const filteredData = res.data.filter(
          (item) => item.bikeGPSList.length > 0 && item.bikeGPSList[0].length > 0
        )
        originData.value = filteredData
        reset()
        if (originData.value.length !== 0) {
          await handleStartAndEnd()
          await handleOriginData()
          handleCoverInit()
        } else {
          ElMessage.error('gps暂无数据')
        }
      } else {
        reset()
      }
      loading.value = false
    }
  } catch (error) {
    console.error(error)
  }
}
/**
 * 定义返回item
 */
interface newItemType extends queryBikeTrackResponseData {
  firstAndLastGpsLngLatList: AMap.LngLat[]
  distance: number
  time: string
  LngLatList: AMap.LngLat[]
  startAddress: string
  endAddress: string
}
/**
 * originData-bikeGPSList 二维数组 每一天的gps数据为一组
 * @constant handledData - 经map处理后的数据
 * @constant totalLngLat - originGps转为LngLat 用于轨迹回放找到index
 * @constant stepData - 开关锁数据中为横跨的数据
 */
const handledData = ref<newItemType[]>([])
const totalLngLat = ref<AMap.LngLat[]>([])
const stepData = ref<newItemType[]>([])
const handleOriginData = async () => {
  const promises = originData.value.map(async (data, i) => {
    const newData: newItemType = {
      firstAndLastGpsLngLatList: [],
      distance: 0,
      time: '',
      LngLatList: [],
      startAddress: '',
      endAddress: '',
      ...data
    }
    /** 展平二维数组 */
    const arr = data.bikeGPSList.flat()
    // if (arr.length == 0) {
    //   ElMessage.error('gps暂无数据')
    //   return
    // }
    /** 获取这段开关锁记录的时长 */
    newData.time = handleEveryRecordTime(data)
    /** 将gps数据放入originGps */
    handleOriginGps(arr)
    /** 并originGps转为LngLat 用于轨迹回放找到index */
    totalLngLat.value = handleGPSToLngLat(originGps.value)
    /** 将数组中的每个gps数据转为LngLat格式  */
    newData.LngLatList = handleGPSToLngLat(arr)
    /** 将第一个gps及最后一个gps放入到firstAndLastGpsLngLatList  */
    newData.firstAndLastGpsLngLatList.push(newData.LngLatList[0])
    newData.firstAndLastGpsLngLatList.push(newData.LngLatList[newData.LngLatList.length - 1])
    /** 这一段开关锁记录的距离 */
    newData.distance = getDistanceOfLine(newData.LngLatList)
    await handleLastTrip(data, newData, arr, i)
    handleNoStep(data, newData, arr, i)
    handleListAddress()
    await handleTotalTimeAndDistance(data.bikeGPSList)
    if (data.step) stepData.value.push(newData)
    return newData
  })
  const processedTrips = await Promise.all(promises) // 等待所有元素处理完毕
  handledData.value = processedTrips
}
/**
 * 处理首尾点数据
 * @interface startType 开始点类型
 * @interface endType 结束点类型
 * @constant start 开始点
 * @constant end 结束点
 */
interface startType {
  LngLat: AMap.LngLat | null
  unlockTime: string
  address: string
}
interface endType {
  LngLat: AMap.LngLat | null
  lockTime: string
  address: string
}
const start = reactive<startType>({ LngLat: null, unlockTime: '', address: '' })
const end = reactive<endType>({ LngLat: null, lockTime: '', address: '' })
const handleStartAndEnd = async () => {
  const firstData = originData.value[0] //第一个开关锁数据
  const lastData = originData.value[originData.value.length - 1] //最后一个开关锁数据
  /**
   * 取最后一个开关锁数据的最后一个gps
   * @param bikeGPSList 二维数组
   * @param LastDataBikeGPSListLength  二维数组的长度
   * @param LastDataBikeGPSListLastData  二维数组最后一个数组
   * @param LastDataBikeGPSListLastDataLength  二维数组最后一个数组的长度
   * @param LastDataBikeGPSListLastDataLastGPS 二维数组最后一个数组的最后一个gps
   */
  const LastDataBikeGPSListLength = lastData.bikeGPSList.length
  const LastDataBikeGPSListLastData = lastData.bikeGPSList[LastDataBikeGPSListLength - 1]
  const LastDataBikeGPSListLastDataLength = LastDataBikeGPSListLastData.length - 1
  const LastDataBikeGPSListLastDataLastGPS =
    LastDataBikeGPSListLastData[LastDataBikeGPSListLastDataLength]
  /**
   * 取第一个开关锁数据的第一个gps数据
   */
  const FirstDataBikeGPSList = firstData.bikeGPSList
  const FirstDataBikeGPSListFirstGps = FirstDataBikeGPSList[0][0]
  if (firstData.step) {
    start.LngLat = new AMap.LngLat(
      Number(FirstDataBikeGPSListFirstGps.longtitude),
      Number(FirstDataBikeGPSListFirstGps.latitude)
    )

    start.unlockTime = FirstDataBikeGPSListFirstGps.recordTime
  } else {
    start.LngLat = new AMap.LngLat(
      Number(firstData.unlockLongtitude),
      Number(firstData.unlockLatitude)
    )
    start.unlockTime = firstData.unlockTime
  }
  const LastGpsLngLat = new AMap.LngLat(
    Number(LastDataBikeGPSListLastDataLastGPS.longtitude),
    Number(LastDataBikeGPSListLastDataLastGPS.latitude)
  )
  const LastGpsRecordTime = LastDataBikeGPSListLastDataLastGPS.recordTime
  /** 若无lockTime 则在骑行中 获取最后一个gps点 */
  if (isRiding(lastData)) {
    end.LngLat = LastGpsLngLat
    end.lockTime = LastGpsRecordTime
  } else {
    /** 否则取最后一段的数据 */
    /** 若跨天 */
    if (lastData.step) {
      end.LngLat = LastGpsLngLat
      end.lockTime = LastGpsRecordTime
    } else {
      end.LngLat = new AMap.LngLat(Number(lastData.lockLongtitude), Number(lastData.lockLatitude))
      end.lockTime = lastData.lockTime
    }
  }
  try {
    const address = await getAddress([start.LngLat, end.LngLat])
    start.address = address[0].formattedAddress
    end.address = address[1].formattedAddress
  } catch (error) {
    console.error(error)
  }
}
/**
 * @method handleLastTrip - 若当天为该开关锁记录的横跨的最后一天 将每天最后一个gps作为横跨点 并计算该点到开锁点的距离及时长
 * @constant stepGpsList - 红边圆点数据
 * @constant list - 地图显示的开关锁数据
 * @interface listType - 开关锁数据类型
 */
const stepGpsList = ref<bikeGPSListType[]>([])
interface listType {
  firstAndLastGpsLngLatList: AMap.LngLat[]
  LngLatList: AMap.LngLat[]
  time: string
  startAddress: string
  startTime: string
  startIcon: string
  endAddress: string
  endTime: string
  endIcon: string
  distance: number
  address?: any
  inBikeGPSListIndex: number
}

const list = ref<listType[]>([])
const handleLastTrip = async (
  data: queryBikeTrackResponseData,
  newData: newItemType,
  flatBikeGPSList: bikeGPSListType[],
  i: number
) => {
  try {
    if (data.step && data.tripStatus == 2) {
      const promises = data.bikeGPSList.map(async (dayGps: bikeGPSListType[], dayI: number) => {
        /** 横跨点 */
        const stepGps = dayGps[dayGps.length - 1]
        const time = handleTimeDuration(stepGps.recordTime, data.unlockTime)
        stepGps.time = time.days() > 0 ? time.format('D天HH小时ss秒') : time.format('HH:mm:ss')
        const index = originGps.value.findIndex((gps) => gps.recordTime === stepGps.recordTime)
        stepGps.distance = getDistanceOfLine(newData.LngLatList.slice(0, index + 1))
        const LngLat = new AMap.LngLat(Number(stepGps.longtitude), Number(stepGps.latitude))
        const address = await getAddress(LngLat)
        stepGps.address = address.formattedAddress
        if (dayI !== data.bikeGPSList.length - 1) {
          stepGpsList.value.push(stepGps)
        }
        return dayGps
      })
      const processedTrips = await Promise.all(promises)
      data.bikeGPSList = processedTrips
      list.value.unshift({
        firstAndLastGpsLngLatList: newData.firstAndLastGpsLngLatList,
        LngLatList: newData.LngLatList,
        time: newData.time,
        startAddress: newData.startAddress,
        startTime: flatBikeGPSList[0].recordTime,
        startIcon: StartIcon,
        endAddress: newData.endAddress,
        endTime: flatBikeGPSList[flatBikeGPSList.length - 1].recordTime,
        endIcon: isRiding(data) ? CyclingIcon : EndIcon,
        distance: newData.distance,
        inBikeGPSListIndex: i
      })
    }
  } catch (error) {
    console.error(error)
  }
}
/**
 * @method handleNoStep - 若该开关锁记录不为横跨 则将该条记录插入列表第一位
 */
const handleNoStep = (
  data: queryBikeTrackResponseData,
  newData: newItemType,
  flatBikeGPSList: bikeGPSListType[],
  i: number
) => {
  if (!data.step) {
    list.value.unshift({
      firstAndLastGpsLngLatList: newData.firstAndLastGpsLngLatList,
      LngLatList: newData.LngLatList,
      time: newData.time,
      startAddress: newData.startAddress,
      startTime: flatBikeGPSList[0].recordTime,
      startIcon: StartIcon,
      endAddress: newData.endAddress,
      endTime: flatBikeGPSList[flatBikeGPSList.length - 1].recordTime,
      endIcon: isRiding(data) ? CyclingIcon : EndIcon,
      distance: newData.distance,
      inBikeGPSListIndex: i
    })
  }
}
/**
 * @method handleListAddress -  由于根据坐标获取地址是异步的 统一在这处理list 的开关锁地址
 */
const handleListAddress = () => {
  try {
    list.value.forEach(async (l) => {
      const address = await getAddress(l.firstAndLastGpsLngLatList)
      l.address = address
      l.startAddress = l.address[0].formattedAddress
      l.endAddress = l.address[1].formattedAddress
    })
  } catch (error) {
    console.error(error)
  }
}
/**
 * 计算当天00：00：00 - 23：59：59的骑行时长 以及骑行距离
 * 即 找到在bikeGPSList中与this.time相符的数组
 * @constant totalDayGps - 当天全部gps数据
 * @constant totalTodayLngLat 当天全部LngLat数据 即由totalDayGps转换而来
 * @constant totalTodayDistance 计算当天骑行距离 由totalTodayLngLat为数据进行计算
 * @constant totalTodayTime 计算当天骑行时间
 */
const totalDayGps = ref<bikeGPSListType[]>([])
const totalTodayLngLat = ref<AMap.LngLat[]>([])
const totalTodayDistance = ref<number>(0)
const totalTodayTime = ref<duration.Duration>()
const formatTotalTime = computed(() =>
  totalTodayTime.value ? totalTodayTime.value.format('HH:mm:ss') : ''
)
const handleTotalTimeAndDistance = (data: bikeGPSListType[][]) => {
  const dayData = data.find((dayGps) => {
    const firstgps = dayGps[0]
    if (time.value === firstgps.recordTime.slice(0, 10)) return true
  })
  totalDayGps.value = totalDayGps.value.concat(dayData ?? [])
  totalDayGps.value = totalDayGps.value.sort(
    (prev, current) => dayjs(prev.recordTime).unix() - dayjs(current.recordTime).unix()
  )
  totalTodayLngLat.value = handleGPSToLngLat(totalDayGps.value)
  totalTodayDistance.value = getDistanceOfLine(totalTodayLngLat.value)

  totalTodayTime.value = handleTimeDuration(
    totalDayGps.value[totalDayGps.value.length - 1].recordTime,
    totalDayGps.value[0].recordTime
  )
}
/**
 * @method handleCoverInit 处理数据生成地图覆盖物
 * @constant marker 骑行车辆
 * @constant polyLines - 每个开关锁数据的轨迹线段数组
 * @constant passedPolyline - 车辆轨迹播放时经过的线段
 * @constant startMarker 开锁点
 * @constant endMarker 关锁点
 * @constant stepMarkers stepMarker横跨点数组
 */
const marker = ref<AMap.Marker>()
const polyLines = ref<AMap.Polyline[]>([])
const passedPolyline = ref<AMap.Polyline>()
const startMarker = ref<AMap.Marker>()
const endMarker = ref<AMap.Marker>()
const stepMarkers = ref<AMap.Marker[]>([])
const handleCoverInit = () => {
  marker.value = new AMap.Marker({
    map: map.value!,
    position: start.LngLat!,
    icon: MarkerIcon,
    offset: new AMap.Pixel(-29, -53)
  })
  handledData.value.forEach((item) => {
    const polyline = new AMap.Polyline({
      map: map.value!,
      path: item.LngLatList,
      strokeColor: '#606266',
      strokeOpacity: 1,
      strokeWeight: 6,
      strokeStyle: 'solid',
      showDir: true,
      lineJoin: 'round'
    })
    polyLines.value.push(polyline)
  })
  //经过线段
  passedPolyline.value = new AMap.Polyline({
    map: map.value!,
    strokeColor: '#ff7880',
    strokeOpacity: 1,
    strokeWeight: 6,
    strokeStyle: 'solid',
    showDir: true,
    lineJoin: 'round'
  })
  //定义车辆回放轨迹事件 在执行moveTo，moveAlong动画时触发事件
  marker.value.on('moving', handleBikeMoving)
  marker.value.on('movealong', handleBikeMovealong)
  /**
   * 生成起点终点 横跨点覆盖物
   * stepData 横跨数据
   * 若长度大于1 列表头尾都是横跨数据 索引0为这段开关锁记录的最后一天 需要将红边圆点显示  2为开关锁记录的第一天 需显示经过点
   * 若长度为1 需要看tripStatus  若为0则需要显示经过图标（不需要显示终点图标） 若为1 则开关锁都为经过图标 若为2 则需要显示红边圆点
   * 若没有长度 则为正常起点终点
   */
  if (stepData.value.length > 1) {
    startMarker.value = getStartMarkerCover(MarkerType.Start, -29, -90)
    //红边圆点
    stepGpsList.value.forEach((step) => {
      const stepMarker = getStepMarkerCover(step, MarkerType.Cross, -5, -47)
      stepMarkers.value.push(stepMarker)
    })
    endMarker.value = getEndMarkerCover(MarkerType.Cross, -29, -90)
  } else if (stepData.value.length == 1) {
    const onlyData = stepData.value[0]
    if (onlyData.tripStatus === 0) {
      startMarker.value = getStartMarkerCover(MarkerType.Start, -29, -90)
      endMarker.value = getEndMarkerCover(MarkerType.Cross, -29, -90)
    } else if (onlyData.tripStatus === 1) {
      startMarker.value = getStartMarkerCover(MarkerType.Cross, -29, -55)
      endMarker.value = getEndMarkerCover(MarkerType.Cross, -28, 0)
    } else {
      startMarker.value = getStartMarkerCover(MarkerType.Start, -29, -90)
      endMarker.value = getEndMarkerCover(MarkerType.End, -28, -47)
      //红边圆点
      stepGpsList.value.forEach((step) => {
        const stepMarker = getStepMarkerCover(step, MarkerType.Step, -5, -47)
        stepMarkers.value.push(stepMarker)
      })
    }
  } else {
    startMarker.value = getStartMarkerCover(MarkerType.Start, -29, -90)
    endMarker.value = getEndMarkerCover(MarkerType.End, -28, -47)
  }
  map.value?.setFitView([startMarker.value, endMarker.value])
}
/**
 * 用于生成content得点类型
 */
enum MarkerType {
  Start = 'start',
  End = 'end',
  Cross = 'cross',
  Step = 'step'
}
/**
 * 生成起点
 */
const getStartMarkerCover = (contentType: MarkerType, x: number, y: number) => {
  return new AMap.Marker({
    position: start.LngLat!,
    map: map.value!,
    content: createContent(contentType, start.address, start.unlockTime),
    offset: new AMap.Pixel(x, y),
    topWhenClick: true
  })
}
/**
 * 生成终点
 */
const getEndMarkerCover = (contentType: MarkerType, x: number, y: number) => {
  return new AMap.Marker({
    position: end.LngLat!,
    map: map.value!,
    content: createContent(contentType, end.address, end.lockTime),
    offset: new AMap.Pixel(x, y),
    anchor: 'middle-left',
    topWhenClick: true
  })
}
/**
 * 生成横跨点
 */
const getStepMarkerCover = (
  data: bikeGPSListType,
  contentType: MarkerType,
  x: number,
  y: number
) => {
  return new AMap.Marker({
    position: new AMap.LngLat(Number(data.longtitude), Number(data.latitude)),
    map: map.value!,
    content: createContent(
      contentType,
      data.address ?? '',
      data.recordTime,
      data.distance,
      data.time
    ),
    offset: new AMap.Pixel(x, y),
    draggable: true
  })
}
/**
 * 创建覆盖物内容
 * @param name 所创建的覆盖物是 起点 终点 经过点 横跨点
 * @param address 覆盖物地址
 * @param recordTime 该覆盖物记录的时间
 * @param 覆盖物距离起点(经过点)长度
 * @param time 覆盖物离起点(经过点)时长
 */
const createContent = (
  name: MarkerType,
  address: string,
  recordTime: string,
  distance?: number,
  time?: string
) => {
  switch (name) {
    case MarkerType.Start:
      return `
                <div class="start_marker_content">
                  <img src="${StartMarkerIcon}"/>
                  <div class="info_content">
                    <div class="address"><span>${address}</span></div>
                    <div class="time"><span>${recordTime}</span></div>
                  </div>
                </div>
          `
    case MarkerType.End:
      return `
                <div class="end_marker_content">
                  <div class="info_content">
                    <div class="address"><span>${address}</span></div>
                    <div class="time"><span>${recordTime}</span></div>
                  </div>
                  <img src="${EndMarkerIcon}"/>
                </div>
                `
    case MarkerType.Cross:
      return `
                <div class="start_marker_content">
                 <img src="${CrossMarkerIcon}"/>
                  <div class="info_content">
                    <div class="address"><span>${address}</span></div>
                    <div class="time"><span>${recordTime}</span></div>
                  </div>
                </div>
                `
    case MarkerType.Step:
      return `
                <div class="step_marker_content">
                  <div class="circle_marker"></div>
                  <div class="info_content">
                    <div class="address"><span>${address}</span></div>
                    <div class="time"><span>${recordTime}</span></div>
                  </div>
                  <div class="info_content2 address">
                    <span>骑行距离:${formatMeter(distance ?? 0)}</span>
                    <span>时长:${time}</span>
                  </div>
                </div>
                `
    default:
      break
  }
}
/**
 *
 */
// const customEasing = (passedTime?: number) => {
//   // 比如一个简单的线性缓动函数
//   return passedTime
// }
/**
 * @description 轨迹回放事件回调函数
 * @param e 事件参数 包含 {index:number,process:number,type:string,passedPath:Proxy(t)[],passedPos:Proxy(t),pos:t}
 * @param process - 动画进程 当为1时代表 点到点的动画结束
 * @param index - 在轨迹数据数组中的index索引
 */
const handleBikeMoving = (e: any) => {
  if (e.progress === 1) {
    marker.value?.setLabel({
      content: `${originGps.value[e.index].recordTime}`,
      direction: 'top'
    })
  }
  passedPolyline.value?.setPath(e.passedPath)
}
/**
 * 执行movealong动画后事件
 * @constant isPlay - 控制车辆是否播放轨迹 通过button的type进行区分
 */
const isPlay = ref<'' | 'default' | 'success' | 'warning' | 'info' | 'text' | 'primary' | 'danger'>(
  ''
)
const handleBikeMovealong = () => {
  isPlay.value = ''
}
/**
 * 当鼠标悬浮于某个开关锁数据列表 将线段颜色标红
 */
const changeShowPolyLine = (e: Event, index: number) => {
  //list的index
  const parent: HTMLElement[] = Array.from(document.querySelectorAll('.bikelocus_record_list_item'))
  for (const child of parent) {
    child.style.background = 'var(--xy-hover-color)'
  }
  const v = list.value[index].inBikeGPSListIndex //找到在bikeGPSList的位置
  polyLines.value.forEach((poly) => {
    poly.setOptions({
      strokeColor: '#999999'
    })
  })
  if (e.type == 'mouseover') {
    ;(e.currentTarget as HTMLElement).style.background = 'rgba(255,109,117,0.1)'
    polyLines.value[v].setOptions({
      strokeColor: 'var(--xy-primary-color)'
    })
  }
}
/**
 * 播放轨迹
 */
const playLocus = () => {
  if (isPlay.value == 'primary') {
    isPlay.value = ''
    marker.value?.moveAlong(totalTodayLngLat.value, {
      aniInterval: 0,
      autoRotation: false,
      duration: 1000
    })
    marker.value?.stopMove()
    // marker.value?.setPosition(start.LngLat!)
    marker.value?.setLabel({
      content: ''
    })
  } else {
    isPlay.value = 'primary'
    if (polyLines.value.length > 0) {
      marker.value?.moveAlong(totalTodayLngLat.value, {
        aniInterval: 0,
        autoRotation: false,
        duration: 1000
      })
    }
  }
}
/** --------------------------辅助函数-------------------------------------------- */
/**
 * 处理每个开关锁记录轨迹时长
 * 若骑行中 时长计算 - 最后一个gps时间与开锁时间的时长
 *  若不为骑行中 时长计算 - 开关锁时间时长
 * @param time - dayjs格式时间
 * @param formatTime - 格式化时间
 * @param last2DArrayData - 二维数组最后一个数组
 * @param lastGpsTime - 最后一个gps的recordTime
 */
const handleEveryRecordTime = (data: queryBikeTrackResponseData) => {
  const last2DArrayData = data.bikeGPSList[data.bikeGPSList.length - 1]
  const lastGpsTime = last2DArrayData[last2DArrayData.length - 1].recordTime
  const time = isRiding(data)
    ? handleTimeDuration(lastGpsTime, data.unlockTime)
    : handleTimeDuration(data.lockTime, data.unlockTime)

  const formatTime = time.days() > 0 ? time.format('D天HH小时mm分钟ss秒') : time.format('HH:mm:ss')

  return formatTime
}
/**
 * 将二维数组中的每个gps数据放入originGps数组
 * @constant originGps - 全部原生接口gps数据
 */
const originGps = ref<bikeGPSListType[]>([])
const handleOriginGps = (data: bikeGPSListType[]) => {
  data.forEach((gps) => originGps.value.push(gps))
}
/**
 * 将数组中的每个gps数据转为LngLat格式
 */
const handleGPSToLngLat = (data: bikeGPSListType[]) => {
  return data.map((gps) => new AMap.LngLat(Number(gps.longtitude), Number(gps.latitude)))
}
/**
 * 使用 dayjs的 duration插件 及 diff方法 计算时长
 */
const handleTimeDuration = (firstTime: string, lastTime: string) => {
  return dayjs.duration(dayjs(firstTime).diff(lastTime))
}
/**
 * 判断是否骑行中
 */
const isRiding = (data: queryBikeTrackResponseData) => {
  return data.lockTime === '' || data.lockTime === null
}
/** 获取地址 */
const getAddress = (data: AMap.LngLat[] | AMap.LngLat): any => {
  return new Promise((resolve, reject) => {
    geocoder.value.getAddress(data, (status: string, result: any) => {
      if (status === 'complete') {
        if (Array.isArray(data)) {
          resolve(result.regeocodes)
        } else {
          resolve(result.regeocode)
        }
      } else {
        reject(new Error(`获取地址失败`))
      }
    })
  })
}
/**
 * 清空所有地图数据
 */
const reset = () => {
  polyLines.value = []
  totalTodayLngLat.value = []
  originGps.value = []
  list.value = []
  stepData.value = []
  stepGpsList.value = []
  stepMarkers.value = []
  totalTodayTime.value = dayjs.duration(0)
  totalTodayDistance.value = 0
  totalDayGps.value = []
  map.value?.clearMap()
}
/**
 * 计算线段的距离
 */
const getDistanceOfLine = (line: AMap.LngLatLike[] | AMap.LngLat[]) => {
  return AMap.GeometryUtil.distanceOfLine(line)
}
</script>

<template>
  <div class="xy-map-container">
    <div ref="mapContainer" id="map-container" v-loading="loading">
      <search-place :auto="auto" :map="map!" :place-search="placeSearch" />
      <div
        v-if="dialogVisible"
        class="bike-locus-dialog"
        :class="{ hasList: list.length > 0 ? true : false }"
      >
        <div class="el-dialog__header">
          <div flex justify-between items-center mb-5>
            <el-date-picker
              v-model="time"
              type="date"
              value-format="YYYY-MM-DD"
              format="YYYY-MM-DD"
              :disabled-date="disabledDate"
              @change="getBikeTrackData"
            />
            <el-button round :type="isPlay" @click="playLocus">
              <el-icon><VideoPlay /></el-icon>
              播放轨迹</el-button
            >
          </div>
          <span class="dialog_header_tip"
            >今日(00:00-23:59)骑行<span class="text-[#333333]">{{
              formatMeter(totalTodayDistance)
            }}</span
            >,骑行时长<span class="text-[#333333]">{{ formatTotalTime }}</span></span
          >
        </div>
        <div class="el-dialog__body">
          <el-scrollbar>
            <div class="bikelocus_record_list" flex flex-col items-center>
              <div
                v-for="(item, index) in list"
                :key="index"
                class="bikelocus_record_list_item"
                flex
                flex-col
                items-center
                @mouseover="changeShowPolyLine($event, index)"
                @mouseout="changeShowPolyLine($event, index)"
              >
                <div>
                  <div>
                    <img :src="item.startIcon" alt="" srcset="" />
                    <div class="item_step_line" />
                    <img :src="item.endIcon" alt="" srcset="" />
                  </div>
                  <div>
                    <div>
                      <div v-if="item.startAddress !== ''">{{ item.startAddress }}</div>
                      <div>{{ item.startTime }}</div>
                    </div>
                    <div>
                      <div v-if="item.endAddress !== ''">{{ item.endAddress }}</div>
                      <div>{{ item.endTime }}</div>
                    </div>
                  </div>
                </div>
                <div flex items-center>
                  <div flex flex-col items-center>
                    <span>{{ formatMeter(item.distance) }}</span>
                    <span>骑行里程</span>
                  </div>
                  <div flex flex-col items-center>
                    <span>{{ item.time }}</span>
                    <span>骑行时长</span>
                  </div>
                </div>
              </div>
            </div>
          </el-scrollbar>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
:deep(.bike_locus_dialog) {
  animation: anim-open-left 0.8s linear;
}
:deep(.start_marker_content) {
  display: flex;
  flex-direction: column;
  width: 250px;

  border-radius: 4px 4px 4px 4px;
  > img {
    width: 59px;
    height: 63px;
  }
  > div {
    margin-left: 5px;
    position: relative;
  }
  div.info_content {
    background: #fff;
    display: flex;
    flex-direction: column;
    padding: 5px;
    box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.25);
  }
}
:deep(.end_marker_content) {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  width: 250px;
  border-radius: 4px 4px 4px 4px;
  > img {
    width: 59px;
    height: 63px;
  }
  > div {
    position: relative;
  }
  div.info_content {
    background: #fff;
    display: flex;
    flex-direction: column;
    padding: 5px;
    box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.25);
  }
}
:deep(.step_marker_content) {
  display: flex;
  flex-direction: column;
  .circle_marker {
    width: 16px;
    height: 16px;
    background: #ffffff;
    border: 3px solid var(--xy-primary-color);
    border-radius: 50%;
  }
  > div.info_content {
    background: #fff;
    padding: 5px;
    display: flex;
    flex-direction: column;
    position: relative;
    margin-left: 50px;
  }
  > div.info_content2 {
    display: flex;
    flex-direction: row;
    background: #fff;
    padding: 5px;
    margin-top: 10px;
    margin-left: 50px;
    > span {
      margin-right: 20px;
    }
  }
}
:deep(.address) {
  font-size: 14px;
  font-family: PingFang SC;
  line-height: 20px;
  color: var(--xy-medium-text-color);
}
:deep(.time) {
  font-size: 12px;
  font-family: PingFang SC;
  line-height: 17px;
  color: var(--xy-grey-text-color);
}
:deep(.hasList) {
  animation:
    anim-open-left 0.8s linear,
    anim-height 0.8s linear;
  height: calc(100% - 130px);
}
@keyframes anim-open-left {
  0% {
    transform: translate3d(-100%, 0, 0);
    opacity: 0;
  }
  25% {
    transform: translate3d(-60%, 0, 0);
    opacity: 0.5;
  }
  50% {
    transform: translate3d(-15%, 0, 0);
    opacity: 0.9;
  }
  75% {
    transform: translate3d(5%, 0, 0);
    opacity: 0.95;
  }
  100% {
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
}
@keyframes anim-height {
  0% {
    height: 0%;
  }
  25% {
    height: 25%;
  }
  50% {
    height: 50%;
  }
  75% {
    height: 75%;
  }
  100% {
    height: 100%;
  }
}
:deep(.el-button.is-round) {
  &:active,
  &:focus,
  &:hover {
    color: #606266;
    border-color: #dcdfe6;
    background: #fff;
  }
}
:deep(.el-button.el-button--primary.is-round) {
  &:active,
  &:focus,
  &:hover {
    color: #fff;
    border-color: var(--xy-primary-color);
    background: var(--xy-primary-color);
  }
}
:deep(.amap-marker-label) {
  background-color: #fff;
  white-space: nowrap;
  box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.25);
  border-radius: 4px 4px 4px 4px;
  cursor: default;
  padding: 3px;
  font-size: 12px;
  line-height: 14px;
  color: #333333;
  border: none;
}
</style>
